package v1

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
	"golang.org/x/sync/errgroup"
	"math/rand"
	"maya-service/bll"
	log "maya-service/collector/logger"
	"maya-service/collector/trace_log"
	"maya-service/constant"
	"maya-service/event"
	"maya-service/model"
	modelEvent "maya-service/model/event"
	"maya-service/model/po"
	"maya-service/server/web/middleware"
	"maya-service/store/redis"
	"maya-service/utils"
	"maya-service/utils/request"
	"time"
)

var DeliverOrder = &deliverOrder{}

func init() {
	RegisterRouter(DeliverOrder)
}

type deliverOrder struct{}

// Init
func (a *deliverOrder) Init(r *gin.RouterGroup) {
	g := r.Group("/deliver", middleware.Auth())
	{
		g.POST("/deliverOrder", a.deliverOrder)
		g.POST("/grabOrder", a.grabOrder)
		g.POST("/deliveryGoods", a.deliveryGoods)
	}
}

// delivery 订单发货
func (a *deliverOrder) deliveryGoods(c *gin.Context) {
	var (
		in  = &po.DeliveryGoodsReq{}
		err error
	)

	if err = c.ShouldBindJSON(in); err != nil {
		c.Error(err)
		return
	}

	// 校验订单是否是当前用户的额
	// 获取订单详情
	// 创建群聊
	// 群聊绑定订单
	utils.ResponseOk(c, nil)
	return
}

// grabOrder 抢订单
func (a *deliverOrder) grabOrder(c *gin.Context) {
	var (
		in  = &po.GrabOrderReq{}
		err error
	)

	if err = c.ShouldBindJSON(in); err != nil {
		c.Error(err)
		return
	}

	// 上分布式锁，获取不到锁就返回
	// 订单状态校验
	// 资格校验，是否是督导师、订单是否匹配当前督导师等级
	// 生成抢单记录
	// 更新订单状态为已接单
	// 更新订单大厅状态为已接单
	utils.ResponseOk(c, nil)
	return
}

// deliverOrder 派发订单
func (a *deliverOrder) deliverOrder(c *gin.Context) {
	var (
		in  = &po.DeliverOrderReq{}
		err error
	)

	if err = c.ShouldBindJSON(in); err != nil {
		c.Error(err)
		return
	}

	if in.UserId == "" {
		userId, err := request.GetUserId(c.Request.Context())
		if err != nil {
			c.Error(err)
			return
		}
		in.UserId = userId
	}

	// 上分布式锁
	err = redis.KV.SetNX(c.Request.Context(), fmt.Sprintf("%v", in.AiConsultId), 1, time.Second*10).Err()
	if err != nil {
		utils.ResponseOkWithError(c, "订单正在派单中，请稍后再试")
		return
	}

	// 商品详情
	goodsInfo, _ := bll.Product.Find(c.Request.Context(), &model.ProductInfoRequest{
		Id: in.GoodId,
	})

	if goodsInfo == nil {
		utils.ResponseOkWithError(c, "商品信息获取失败，请稍后再试")
		return
	}

	kfId := constant.GetKfId(goodsInfo.ProductType)
	status := bll.OrderLogicInstance.GetServiceStatus(kfId, in.UserId)
	if status == 3 {
		utils.ResponseOkWithError(c, "上一个对话未结束、可以联系客服进行结束会话即可进行下一个咨询！")
		return
	}

	orderStatus := 6
	err = bll.Order.Update(c.Request.Context(), &model.OrderUpdateRequest{
		CustomerId:     &in.UserId,
		OrderStatus:    &orderStatus,
		SrcOrderStatus: []int{0, 7},
	})
	if err != nil {
		utils.ResponseOkWithError(c, "数据库错误")
		return
	}

	// 当前这个对话是否有未完成的订单
	findOrder, _ := bll.Order.Find(c.Request.Context(), &model.OrderInfoRequest{
		CustomerId:  in.UserId,
		OrderStatus: []int{0},
		ExtraData:   fmt.Sprintf("%v", in.AiConsultId),
	})
	if findOrder != nil && findOrder.Id > 0 {
		utils.ResponseOkWithError(c, "订单派发成功，请耐心等待")
		return
	}

	// 咨询信息
	var consultData = po.ConsultData{
		ConsultId: in.AiConsultId,
	}
	var errGroup errgroup.Group
	errGroup.Go(func() error {
		consultInfo, _ := bll.AiConsult.Find(c.Request.Context(), &model.AiConsultInfoRequest{
			Id: in.AiConsultId,
		})
		if consultInfo != nil && consultInfo.Id > 0 {
			questionInfo, _ := bll.AiQuestion.Find(c.Request.Context(), &model.AiQuestionInfoRequest{Id: consultInfo.QuestionId})
			if questionInfo != nil && questionInfo.Id > 0 {
				consultData.Title = questionInfo.Topic
			}
		}
		return nil
	})

	var deliveryUser = po.DeliveryUser{
		UserId: in.UserId,
	}
	errGroup.Go(func() error {
		userInfo, _ := bll.UserRecord.Find(c.Request.Context(), &model.UserRecordInfoRequest{
			UserId: in.UserId,
		})

		if userInfo != nil && userInfo.Id > 0 {
			deliveryUser.NickName = userInfo.NickName
		}
		return nil
	})

	_ = errGroup.Wait()

	// 创建订单
	orderNo := GenerateOrderID()
	err = bll.Order.Create(c.Request.Context(), &model.OrderCreateRequest{
		OrderId:         orderNo,
		CustomerId:      in.UserId,
		OrderDate:       time.Now().Unix(),
		OrderStatus:     7, // 待发布
		TotalAmount:     0,
		PaymentMethod:   "",
		ShippingAddress: "",
		Remarks:         "咨询答题订单",
		OrderContext: utils.ToJsonString(&po.OrderContext{
			UserId:         in.UserId,
			OrderId:        orderNo,
			GoodId:         in.GoodId,
			ChatContext:    "",
			SupervisorId:   "",
			ConsultContext: consultData,
			DeliveryUser:   deliveryUser,
			Goods:          *goodsInfo,
		}),
		ExtraData: fmt.Sprintf("%v", in.AiConsultId),
	})
	if err != nil {
		utils.ResponseOkWithError(c, "创建订单失败， 请重新尝试")
		return
	}

	trace_log.DebugLogger(orderNo, "########## 生成订单成功，订单为待生效状态 UserId:", in.UserId)
	// 后续可以投递到redis订单大厅，更新本地缓存
	event.Publish(c.Request.Context(), event.OrderCreated, &modelEvent.OrderCreateNotify{
		OrderId: orderNo,
	})

	log.Info("####### deliveryOrder kfId:", zap.Any("kfId", bll.GetKfIdByOrder(orderNo)))
	utils.ResponseOk(c, &po.DeliverOrderRsp{
		OrderId:  orderNo,
		WaitTime: 30,
		KfLink:   constant.GetKfUrl(goodsInfo.ProductType),
	})
	return
}

// GenerateOrderID 生成一个32位的订单号
func GenerateOrderID() string {
	// 获取当前时间戳，精确到毫秒
	timestamp := time.Now().Format("20060102150405") // 格式：YYYYMMDDHHMMSS

	// 生成16位的随机字符串
	randomPart := generateRandomString(16)

	// 拼接时间戳和随机字符串
	orderID := fmt.Sprintf("%s%s", timestamp, randomPart)

	return orderID
}

// generateRandomString 生成指定长度的随机字符串（由数字和小写字母组成）
func generateRandomString(length int) string {
	const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
	b := make([]byte, length)
	_, err := rand.Read(b) // 使用加密安全的随机数
	if err != nil {
		panic(err) // 如果随机数生成失败，直接抛出错误
	}
	for i := range b {
		b[i] = charset[int(b[i])%len(charset)]
	}
	return string(b)
}
